package com.zmj.sy.mom.srv.aps.service;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zmj.sy.mom.srv.aps.bean.entity.base.Pool;
import com.zmj.sy.mom.srv.aps.bean.entity.base.PoolItem;
import com.zmj.sy.mom.srv.aps.bean.entity.base.PoolLog;
import com.zmj.sy.mom.srv.aps.bean.entity.base.PoolPart;
import com.zmj.sy.mom.srv.aps.bean.entity.order.Order;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BasePageResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.omb.*;
import com.zmj.sy.mom.srv.aps.mapper.*;
import com.zmj.sy.mom.srv.aps.utils.MkBeanUtils;
import com.zmj.sy.mom.srv.aps.utils.SyExceptionUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class OrderMaterialBorrowService {

    private final PoolMapper poolMapper;

    private final PoolItemMapper poolItemMapper;

    private final PoolPartMapper poolPartMapper;

    private final PartLogMapper partLogMapper;

    private final PoolLogMapper poolLogMapper;

    public static final String idSpec = "-";
    private final OrderMapper orderMapper;

    @Transactional
    public List<OrderMaterialBorrowTreeResVo> tree(OrderMaterialBorrowTreeReqVo reqVo) {

        // 添加根
        if(!StringUtils.hasText(reqVo.getId())){
            List<OrderMaterialBorrowTreeResVo> resList = new ArrayList<>();
            OrderMaterialBorrowTreeResVo root = new OrderMaterialBorrowTreeResVo("1" + idSpec + "1", null, 1, 1, "订单借料");
            resList.add(root);
            return resList;
        }

        String[] splitArr = reqVo.getId().split(idSpec);
        Integer type = Integer.parseInt(splitArr[0]);
        Integer id = Integer.parseInt(splitArr[1]);
        if(type.equals(1)){
            // 添加零件池
            List<Pool> poolList = poolMapper.lambdaQuery().orderByDesc(Pool::getId).list();
            return poolList.stream()
                    .map(e -> {
                        OrderMaterialBorrowTreeResVo resVo = new OrderMaterialBorrowTreeResVo();
                        resVo.setType(2);
                        resVo.setTargetId(e.getId());
                        resVo.setId(resVo.getType() + idSpec + e.getId());
                        resVo.setPid(reqVo.getId());
                        resVo.setName(e.getName());
                        return resVo;
                    })
                    .collect(Collectors.toList());
        }

        // 查找施工号
        if (type.equals(2)) {
            List<PoolItem> list = poolItemMapper.lambdaQuery().eq(PoolItem::getPoolId, id).list();
            return list.stream()
                    .sorted(Comparator.comparingInt(PoolItem::getSeq))
                    .map(e -> {
                        OrderMaterialBorrowTreeResVo resVo = new OrderMaterialBorrowTreeResVo();
                        resVo.setType(3);
                        resVo.setTargetId(e.getId());
                        resVo.setId(resVo.getType() + idSpec + e.getId());
                        resVo.setPid(reqVo.getId());
                        resVo.setName(e.getConstructCode());
                        return resVo;
                    })
                    .collect(Collectors.toList());
        }

        // 列出施工号的借件关系
        if (type.equals(3)) {
            PoolItem pi = poolItemMapper.selectById( id);
            List<PoolPart> list = poolPartMapper.lambdaQuery()
                    .eq(PoolPart::getTargetCode, pi.getConstructCode())
                    .orderByDesc(PoolPart::getMyCode)
                    .orderByDesc(PoolPart::getPlmId)
                    .orderByDesc(PoolPart::getPhaseCode)
                    .list();
            return list.stream()
                    .map(e -> {
                        OrderMaterialBorrowTreeResVo resVo = new OrderMaterialBorrowTreeResVo();
                        resVo.setType(4);
                        resVo.setTargetId(e.getId());
                        resVo.setId(resVo.getType() + idSpec + e.getId());
                        resVo.setPid(reqVo.getId());
                        resVo.setName(e.getPlmId() + " " + e.getPhaseCode());
                        return resVo;
                    })
                    .collect(Collectors.toList());
        }

        // 不显示 零件日志
//        if (type.equals(4)) {
//            return new ArrayList<>();
//        }

        return new ArrayList<>();
    }

    @Transactional(readOnly = true)
    public BasePageResVo<OrderMaterialBorrowListResVo> list(OrderMaterialBorrowListReqVo reqVo) {
        Page<Pool> page = poolMapper.lambdaQuery()
                .like(StringUtils.hasText(reqVo.getName()), Pool::getName, reqVo.getName())
                .like(StringUtils.hasText(reqVo.getPoolCode()), Pool::getPoolCode, reqVo.getPoolCode())
                .eq(reqVo.getType() != null, Pool::getType, reqVo.getType())
                .eq(reqVo.getStatus() != null, Pool::getStatus, reqVo.getStatus())
                .orderByDesc(Pool::getId)
                .page(reqVo.toPage());
        return BasePageResVo.of(page, OrderMaterialBorrowListResVo.class);
    }

    @Transactional
    public void add(OrderMaterialBorrowAddReqVo reqVo) {
        Pool pool = MkBeanUtils.copyProperties(reqVo, Pool.class);
        pool.setName("未命名");
        pool.setStatus(1);
        poolMapper.insert(pool);
    }

    @Transactional
    public void edit(OrderMaterialBorrowEditReqVo reqVo) {
        Pool pool = MkBeanUtils.copyProperties(reqVo, Pool.class);
        poolMapper.updateById( pool);
    }

    @Transactional
    public void delete(BaseIdReqVo reqVo) {
        Pool pool = poolMapper.selectById(reqVo.getId());
        if(pool.getType().equals(1)){
            throw SyExceptionUtils.e("前七位自动匹配规则，无法删除");
        }

        Integer count = poolItemMapper.lambdaQuery().eq(PoolItem::getPoolId, reqVo.getId()).count();
        if(count > 0){
            throw SyExceptionUtils.e("有子项，无法删除");
        }
        poolMapper.deleteById(reqVo.getId());
    }

    @Transactional(readOnly = true)
    public BasePageResVo<OrderMaterialBorrowConsListResVo> consList(OrderMaterialBorrowConsListReqVo reqVo) {

        Page<PoolItem> page = poolItemMapper.lambdaQuery()
                .eq(PoolItem::getPoolId, reqVo.getPoolId())
                .like(StringUtils.hasText(reqVo.getConstructCode()), PoolItem::getConstructCode, reqVo.getConstructCode())
                .orderByAsc(PoolItem::getSeq)
                .page(reqVo.toPage());
        return BasePageResVo.of(page, OrderMaterialBorrowConsListResVo.class);
    }


    @Transactional
    public void consAdd(OrderMaterialBorrowConsAddReqVo reqVo) {
        Pool pool = poolMapper.selectById(reqVo.getPoolId());
        if(pool.getType().equals(1)){
            throw SyExceptionUtils.e("前七位自动匹配规则，无法创建");
        }

        PoolItem poolItem = MkBeanUtils.copyProperties(reqVo, PoolItem.class);
        Integer count = poolItemMapper.lambdaQuery()
                .eq(PoolItem::getConstructCode, poolItem.getConstructCode())
                .count();
        if(count > 0){
            throw SyExceptionUtils.e("该施工号重复添加");
        }

        poolItem.setPoolId(reqVo.getPoolId());
        poolItemMapper.insert(poolItem);

        List<PoolItem> list = poolItemMapper.lambdaQuery().eq(PoolItem::getPoolId, pool.getId()).list();
        String collect = list.stream().sorted(Comparator.comparing(PoolItem::getSeq)).map(PoolItem::getConstructCode).collect(Collectors.joining(","));
        pool.setName(collect);
        poolMapper.updateById(pool);
    }

    @Transactional
    public void consEdit(OrderMaterialBorrowConsEditReqVo reqVo) {
        PoolItem poolItem = MkBeanUtils.copyProperties(reqVo, PoolItem.class, "constructCode");
        PoolItem poolItem1 = poolItemMapper.selectById(reqVo.getId());
        Pool pool = poolMapper.selectById(poolItem1.getPoolId());

        if(!pool.getType().equals(1)){
            poolItem.setConstructCode(reqVo.getConstructCode());
        }


        Integer count = poolItemMapper.lambdaQuery()
                .eq(PoolItem::getConstructCode, poolItem.getConstructCode())
                .ne(PoolItem::getId, reqVo.getId())
                .count();
        if(count > 0){
            throw SyExceptionUtils.e("该施工号重复添加");
        }

        poolItemMapper.updateById(poolItem);

        List<PoolItem> list = poolItemMapper.lambdaQuery().eq(PoolItem::getPoolId, pool.getId()).list();
        String collect = list.stream().sorted(Comparator.comparing(PoolItem::getSeq)).map(PoolItem::getConstructCode).collect(Collectors.joining(","));
        pool.setName(collect);
        poolMapper.updateById(pool);
    }

    @Transactional
    public void consDelete(BaseIdReqVo reqVo) {
        PoolItem poolItem = poolItemMapper.selectById(reqVo.getId());
        Pool pool = poolMapper.selectById(poolItem.getPoolId());
        if(pool.getType().equals(1)){
            throw SyExceptionUtils.e("前七位自动匹配规则，无法删除");
        }

        Integer count = poolPartMapper.lambdaQuery()
                .eq(PoolPart::getTargetCode, poolItem.getConstructCode())
                .or()
                .eq(PoolPart::getMyCode, poolItem.getConstructCode())
                .count();
        if(count > 0){
            throw SyExceptionUtils.e("有子项，无法删除");
        }

        poolItemMapper.deleteById(reqVo.getId());
    }

    @Transactional(readOnly = true)
    public BasePageResVo<OrderMaterialBorrowPartListResVo> partList(OrderMaterialBorrowPartListReqVo reqVo) {

        PoolItem poolItem = poolItemMapper.selectById(reqVo.getId());
        Page<PoolPart> page = poolPartMapper.lambdaQuery()
//                .eq(PoolPart::getPoolId, poolItem.getPoolId())
                .eq(PoolPart::getTargetCode, poolItem.getConstructCode())
                .page(reqVo.toPage());

        return BasePageResVo.of(page, OrderMaterialBorrowPartListResVo.class);
    }

    @Transactional(readOnly = true)
    public BasePageResVo<OrderMaterialBorrowPartLogResVo> partLog(OrderMaterialBorrowPartLogReqVo reqVo) {

        PoolPart poolPart = poolPartMapper.selectById(reqVo.getId());

        Page<PoolLog> page = poolLogMapper.lambdaQuery()
                .eq(PoolLog::getPlmId, poolPart.getPlmId())
                .eq(PoolLog::getPhaseCode, poolPart.getPhaseCode())
                .and(wr->{
                    wr.eq(PoolLog::getMyCode, poolPart.getMyCode())
                            .or()
                            .eq(PoolLog::getTargetCode, poolPart.getTargetCode());
                })
                .page(reqVo.toPage());

        return BasePageResVo.of(page, OrderMaterialBorrowPartLogResVo.class);

    }


    @Transactional
    public void check(List<Integer> orderIdList) {
        List<Order> orderList = orderMapper.lambdaQuery().in(Order::getId, orderIdList).list();
        List<String> constructNoList = orderList.stream().map(Order::getConstructNo).distinct().collect(Collectors.toList());

        int len = 7;

        for (String constructNo : constructNoList) {
            List<Order> matchOrderList = orderMapper.lambdaQuery().likeRight(Order::getConstructNo, constructNo.substring(0, len)).list();

            List<String> disConsList = matchOrderList.stream().map(Order::getConstructNo).distinct().collect(Collectors.toList());

            if (disConsList.size() <= 1) {
                continue;
            }

            List<PoolItem> list = poolItemMapper.lambdaQuery().in(PoolItem::getConstructCode, disConsList).list();
            Map<String, PoolItem> consCodeMap = list.stream().collect(Collectors.toMap(PoolItem::getConstructCode, e -> e));

            Pool p = null;
            if(CollUtil.isEmpty(list)){
                p = new Pool();
                p.setType(1);
                p.setName(String.join(",", disConsList));
                p.setStatus(1);
                p.setRemark("系统自动生成");
                poolMapper.insert(p);
            } else {
                p = poolMapper.selectById(list.get(0).getPoolId());
                p.setName(String.join(",", disConsList));
                poolMapper.updateById(p);
            }

            for (String cons : disConsList) {
                PoolItem poolItem = consCodeMap.get(cons);
                if(poolItem != null){
                    continue;
                }

                poolItem = new PoolItem();
                poolItem.setPoolId(p.getId());
                poolItem.setConstructCode(cons);
                poolItem.setSeq(1);
                poolItem.setStatus(1);
                poolItemMapper.insert(poolItem);
            }


        }


    }
}
